package cn.csc.module.order.service.order;

import cn.csc.framework.common.exception.ServiceException;
import cn.csc.framework.common.pojo.PageResult;
import cn.csc.framework.mybatis.core.util.MyBatisUtils;
import cn.csc.module.distribute.api.order.DistributeOrderApi;
import cn.csc.module.member.api.address.MemberAddressApi;
import cn.csc.module.member.api.address.dto.MemberAddressRespDTO;
import cn.csc.module.order.api.order.dto.OrderSimpleAmountInfoRespDTO;
import cn.csc.module.order.api.order.dto.OrderStatusRespDTO;
import cn.csc.module.order.controller.admin.addr.vo.OrderAddrBaseVO;
import cn.csc.module.order.controller.admin.item.vo.OrderItemBaseVO;
import cn.csc.module.order.controller.admin.order.vo.*;
import cn.csc.module.order.controller.app.dto.OrderCreateReqDTO;
import cn.csc.module.order.controller.app.order.vo.*;
import cn.csc.module.order.controller.app.vo.OrderRespVO;
import cn.csc.module.order.convert.addr.OrderAddrConvert;
import cn.csc.module.order.convert.item.OrderItemConvert;
import cn.csc.module.order.convert.order.OrderConvert;
import cn.csc.module.order.dal.dataobject.addr.OrderAddrDO;
import cn.csc.module.order.dal.dataobject.item.OrderItemDO;
import cn.csc.module.order.dal.dataobject.order.OrderDO;
import cn.csc.module.order.dal.mysql.addr.OrderAddrMapper;
import cn.csc.module.order.dal.mysql.item.OrderItemMapper;
import cn.csc.module.order.dal.mysql.order.OrderMapper;
import cn.csc.module.order.enums.OrderStatus;
import cn.csc.module.order.enums.OrderStatusEnum;
import cn.csc.module.order.mq.producer.OrderCancelProducer;
import cn.csc.module.order.service.addr.OrderAddrService;
import cn.csc.module.order.service.item.OrderItemService;
import cn.csc.module.order.service.shopcart.ShopCartItemService;
import cn.csc.module.pay.api.order.PayOrderApi;
import cn.csc.module.pay.api.order.dto.CreateDivideWithOrderItemIdReqDTO;
import cn.csc.module.product.api.stocklock.SkuStockLockApi;
import cn.csc.module.product.api.stocklock.dto.SkuStockLockReqDTO;
import cn.csc.module.shop.api.detail.ShopDetailApi;
import cn.csc.module.shop.api.detail.dto.ShopDetailRespDTO;
import cn.csc.module.shoppingCard.api.card.CardApi;
import cn.csc.module.shoppingCard.api.card.dto.CardMultiLockReqDTO;
import cn.csc.module.shoppingCard.api.card.dto.CardRespDTO;
import cn.csc.module.shoppingCard.api.transaction.CardTransactionApi;
import cn.csc.module.shoppingCard.api.transaction.dto.CardTransactionCreateReqDTO;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static cn.csc.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.csc.module.order.enums.ErrorCodeConstants.MQ_SEND_FAIL;
import static cn.csc.module.order.enums.ErrorCodeConstants.ORDER_NOT_EXISTS;

/**
 * 订单信息 Service 实现类
 *
 * @author liuchuang
 */
@Service
@Validated
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderDO> implements OrderService {

    @Resource
    private OrderItemMapper orderItemMapper;
    @Resource
    private OrderAddrMapper orderAddrMapper;

    @Resource
    private OrderItemService orderItemService;
    @Resource
    private OrderAddrService orderAddrService;

    @Resource
    private OrderCancelProducer orderCancelProducer;


    @Autowired
    private MemberAddressApi memberAddressApi;

    @Resource
    private ShopCartItemService shopCartItemService;

    @Autowired
    private ShopDetailApi shopDetailApi;

    @Autowired
    private PayOrderApi payOrderApi;
    @Autowired
    private SkuStockLockApi skuStockLockApi;
    @Autowired
    private CardApi cardApi;
    @Autowired
    private CardTransactionApi cardTransactionApi;

    @Override
    public BigInteger create(OrderCreateReqVO createReqVO) {
        // 插入
        OrderDO orderDO = OrderConvert.INSTANCE.convert(createReqVO);
        baseMapper.insert(orderDO);
        // 返回
        return orderDO.getId();
    }

    @Override
    public void update(OrderUpdateReqVO updateReqVO) {
        // 校验存在
        validateExists(updateReqVO.getId());
        // 更新
        OrderDO updateObj = OrderConvert.INSTANCE.convert(updateReqVO);
        baseMapper.updateById(updateObj);
    }

    /**
     * 支付时更新订单状态
     *
     * @param orderIds 订单id列表
     * @return
     */
    @Override
    public Integer updateOrderState(List<BigInteger> orderIds, Integer orderStatus) {
        return baseMapper.updateOrderState(orderIds, orderStatus);
    }

    /**
     * 将订单改为已支付状态
     *
     * @param merchantOrderId 商户订单编号
     */
    @GlobalTransactional(name = "csc-order-pay", rollbackFor = Exception.class)
    @Transactional
    @Override
    public Integer updateByToPaySuccess(String merchantOrderId) {
        //修改订单子项的支付状态
        OrderDO orderDO = baseMapper.selectByMerchantOrderId(merchantOrderId);
        orderItemMapper.updateByToPaySuccess(Collections.singletonList(orderDO.getId()));
        //删除购物车商品信息(物理删除)
        shopCartItemService.deleteShopCartItemByOrderId(Collections.singletonList(orderDO.getId()));
        // 支付成功后更新库存
        //删除库存
        List<OrderItemDO> orderItemDOList = orderItemService.getItemByOrderId(orderDO.getId());
        this.decreStock(OrderItemConvert.INSTANCE.convertVoList01(orderItemDOList));
        //解锁购物卡
        cardApi.unLock(Collections.singletonList(orderDO.getId()), orderDO.getUserId());
        //更新购物卡金额
        cardTransactionApi.updateStatus(Collections.singletonList(orderDO.getId()));

        return baseMapper.updateByToPaySuccess(merchantOrderId);
    }

    @Override
    public void delete(BigInteger id) {
        // 校验存在
        validateExists(id);
        // 删除
        baseMapper.deleteById(id);
    }

    private void validateExists(BigInteger id) {
        if (baseMapper.selectById(id) == null) {
            throw exception(ORDER_NOT_EXISTS);
        }
    }

    @Override
    public OrderDO get(BigInteger id) {
        return baseMapper.selectById(id);
    }

    /**
     * 查询订单状态
     *
     * @param orderIds 多个订单的订单id
     * @return 订单状态列表
     */
    @Override
    public List<OrderStatusRespDTO> getOrdersStatus(List<BigInteger> orderIds) {
        return baseMapper.getOrdersStatus(orderIds);
    }

    /**
     * 获取订单中的金额信息，不包含退款
     *
     * @param orderIds 多个订单的订单id
     * @return 订单商家id列表
     */
    @Override
    public List<OrderSimpleAmountInfoRespDTO> getOrdersSimpleAmountInfo(List<BigInteger> orderIds) {
        return baseMapper.getOrdersSimpleAmountInfo(orderIds);
    }

    /**
     * 取消订单
     *
     * @param orderIds 订单id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelOrderAndGetCancelOrderIds(List<BigInteger> orderIds) {
        List<OrderStatusRespDTO> ordersStatus = baseMapper.getOrdersStatus(orderIds);
        List<BigInteger> cancelOrderIds = ordersStatus.stream()
                .filter(order -> order.getStatus() != null && Objects.equals(order.getStatus(), OrderStatus.UNPAY.value()))
                .map(OrderStatusRespDTO::getOrderId)
                .collect(Collectors.toList());
        if (CollectionUtil.isEmpty(cancelOrderIds)) {
            return;
        }
        baseMapper.cancelOrders(cancelOrderIds);
        // 解锁库存状态
        Boolean sendFlag = orderCancelProducer.sendOrderCancelMessage(orderIds);
        if (!sendFlag) {
            throw new ServiceException(MQ_SEND_FAIL);
        }
    }

    @Override
    public List<OrderDO> getList(Collection<BigInteger> ids) {
        return baseMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<OrderRespAdminVO> getPage(OrderPageReqVO pageReqVO) {
        PageResult<OrderDO> res = baseMapper.selectAdminPage(pageReqVO);
        PageResult<OrderRespAdminVO> result = OrderConvert.INSTANCE.convertPage(res);
        List<OrderDO> list = res.getList();
        List<OrderRespAdminVO> resultList = new ArrayList<>();
        for (OrderDO orderDO : list) {
            log.info("[OrderServiceImpl][getPage][orderDO]=={}", orderDO);
            OrderRespAdminVO orderRespVO = OrderConvert.INSTANCE.convert(orderDO);
            //查询产品信息
            List<OrderItemDO> itemDOS = orderItemService.getItemByOrderId(orderDO.getId());
            log.info("[OrderServiceImpl][getPage][itemDOS]=={}", itemDOS);
            orderRespVO.setSkuName(itemDOS.get(0).getSkuName());
            orderRespVO.setPrice(itemDOS.get(0).getPrice());
            resultList.add(orderRespVO);
        }
        result.setList(resultList);
        return result;
    }

    /**
     * 获得订单信息分页,包含订单子项
     *
     * @param pageReqVO 分页查询
     * @return 订单信息分页
     */
    @Override
    public PageResult<OrderWithItemRespVO> selectOrderWithItemsPage(OrderPageReqVO pageReqVO) {
        IPage<OrderWithItemRespVO> mpPage = MyBatisUtils.buildPage(pageReqVO);
        baseMapper.selectOrderWithItemsPage(pageReqVO, mpPage);
        long totalPage;
        // 多表关联使用mpPage.getRecords().size()
        if (mpPage.getRecords().size() > 0) {
            if (mpPage.getRecords().size() % pageReqVO.getPageSize() <= 0)
                totalPage = mpPage.getRecords().size() / pageReqVO.getPageSize();
            else
                totalPage = (mpPage.getRecords().size() / pageReqVO.getPageSize()) + 1;
        } else {
            return new PageResult<>();
        }

        return new PageResult<>(mpPage.getRecords(), (long) mpPage.getRecords().size(), totalPage);
    }

    /**
     * 分页查询订单信息，包含订单子项和地址
     *
     * @param pageReqVO 分页查询
     * @return
     */
    @Override
    public PageInfo<AppOrderWithItemAndAddrRespVO> selectOrderWithItemsAndAddrsPage(OrderPageReqVO pageReqVO) {
        PageHelper.startPage(pageReqVO.getPageNo(), pageReqVO.getPageSize());
        List<OrderWithItemAndAddrRespVO> list = baseMapper.selectWithItemAndAddrPage(pageReqVO);
        if (!CollectionUtils.isEmpty(list)) {
            List<BigInteger> shopIds = list.stream().map(OrderWithItemAndAddrRespVO::getOrderItems).flatMap(Collection::stream).map(OrderItemBaseVO::getShopId)
                    .distinct().collect(Collectors.toList());
            // 查询店铺信息
            List<ShopDetailRespDTO> shopDetails = shopDetailApi.getShopDetailList(shopIds).getCheckedData();
            Map<BigInteger, String> shopMap = cn.csc.framework.common.util.collection.CollectionUtils.convertMap(shopDetails, ShopDetailRespDTO::getId, ShopDetailRespDTO::getShopName);
            list.stream().map(OrderWithItemAndAddrRespVO::getOrderItems).flatMap(Collection::stream)
                    .forEach(o -> o.setShopName(shopMap.get(o.getShopId())));
            log.info("[OrderServiceImpl][selectOrderWithItemsAndAddrsPage] : {} , {}", list.size(), list);
            List<AppOrderWithItemAndAddrRespVO> records = list.stream().map(o -> {
                AppOrderWithItemAndAddrRespVO convert = OrderConvert.INSTANCE.convert(o);
                convert.setOrderItemMap(cn.csc.framework.common.util.collection.CollectionUtils.convertMultiMap(o.getOrderItems(), OrderItemBaseVO::getShopId));
                convert.setOrderAddrMap(cn.csc.framework.common.util.collection.CollectionUtils.convertMultiMap(o.getOrderAddrList(), OrderAddrBaseVO::getOrderId));
                return convert;
            }).collect(Collectors.toList());
            log.info("[OrderServiceImpl][selectOrderWithItemsAndAddrsPage][records] : {} , {}", records.size(), records);
            return new PageInfo<>(records);
        } else {
            return new PageInfo<>();
        }
    }

    @Override
    public PageResult<OrderWithItemAndAddrRespVO> selectOrderWithItemAndAddrPage(OrderPageReqVO pageReqVO) {
        Page<BigInteger> mpPage = MyBatisUtils.buildPage(pageReqVO);
        // 设置自定义countSql的id
        // mpPage.setCountId("selectWithItemsAndAddrsPageCount");
        baseMapper.selectIdsWithItemsAndAddrsPage(pageReqVO, mpPage);  // 分页查询符合条件的订单ID
        log.info("selectOrderWithItemsAndAddrsPage mpPage: {}", mpPage);
        if (mpPage.getRecords().size() > 0) {
            OrderExtPageReqVO reqVO = OrderConvert.INSTANCE.convert(pageReqVO);
            reqVO.setOrderIds(mpPage.getRecords());
            List<OrderWithItemAndAddrRespVO> list = baseMapper.selectWithItemsAndAddrsList(reqVO);
            log.info("selectOrderWithItemsAndAddrsPage: {}, {}, {}", mpPage.getTotal(), mpPage.getRecords().size(), mpPage.getRecords());
            return new PageResult<>(list, mpPage.getTotal(), mpPage.getPages());
        } else {
            return new PageResult<>(Collections.emptyList(), mpPage.getTotal(), mpPage.getPages());
        }

    }


    /**
     * 查询订单信息，包含订单子项
     *
     * @param merchantOrderId 订单ID
     * @return
     */
    @Override
    public OrderWithItemRespVO selectOrderWithItems(String merchantOrderId) {
        return baseMapper.selectOrderWithItems(merchantOrderId);
    }

    @Override
    public List<OrderDO> getExportList(OrderPageReqVO pageVO) {
        return baseMapper.selectExportList(pageVO);
    }

    @Transactional(rollbackFor = Exception.class)
    public BigInteger saveOrder(OrderCreateReqDTO orderDTO) {
        log.info("[OrderServiceImpl][saveOrder][orderDTO]: {}", orderDTO);
        OrderDO orderDO = OrderConvert.INSTANCE.convert2(orderDTO);
        baseMapper.insert(orderDO);

        //保存订单项 (单个sku)
        OrderItemDO orderItemDO = OrderItemDO.builder()
                .orderId(orderDO.getId())
                .categoryId(orderDTO.getCategoryId())
                .spuId(orderDTO.getSpuId())
                .spuName(orderDTO.getSpuName())
                .skuId(orderDTO.getSkuId())
                .skuName(orderDTO.getSkuName())
                .price(orderDTO.getProductPrice())
                .count(orderDTO.getAllCount())
                .deliveryType(orderDTO.getDvyType())
                .shopId(orderDTO.getShopId())
                .userId(orderDTO.getUserId())
                .spuTotalAmount(orderDTO.getTotal())
                .pic(orderDTO.getPic())
                .build();
        orderItemMapper.insert(orderItemDO);
        // 通过地址ID查询地址信息
        //保存订单地址
        MemberAddressRespDTO address = memberAddressApi.getAddress(orderDTO.getOrderAddrId().longValue(), orderDTO.getUserId().longValue()).getCheckedData();
        OrderAddrDO addrDO = OrderAddrDO.builder()
                .orderId(orderDO.getId())
                .memberAddrId(orderDTO.getOrderAddrId())
                .orderItemId(orderItemDO.getId())
                .userId(orderDTO.getUserId())
                .consignee(address.getName())
                .provinceId(address.getProvinceId())
                .province(address.getProvince())
                .cityId(address.getCityId())
                .city(address.getCity())
                .areaId(address.getAreaId())
                .area(address.getArea())
                .addrDetail(address.getDetailAddress())
                .mobile(address.getMobile())
                .build();
        orderAddrMapper.insert(addrDO);
        /*
        // 锁定库存
        SkuStockLockReqDTO lockReqDTO = SkuStockLockReqDTO.builder()
                .spuId(orderDTO.getSpuId())
                .skuId(orderDTO.getSkuId())
                .orderId(orderDO.getId())
                .count(orderDTO.getAllCount())
                .build();
        CommonResult<Void> lockStockResponse = skuStockLockApi.lock(Arrays.asList(lockReqDTO));
        // 锁库存失败，抛异常回滚
        if (!lockStockResponse.isSuccess()){
            throw new ServiceException(lockStockResponse.getCode(),lockStockResponse.getMsg());
        }
        // 发送延迟消息，如果三十分钟后没有支付，则取消订单
        Boolean sendFlag = orderCancelProducer.sendOrderCancelMessage(Arrays.asList(orderDO.getId()));
        if (!sendFlag){
            // 消息发送失败，则抛异常回滚
            throw new ServiceException(MQ_SEND_FAIL);
        }
         */
        return orderDO.getId();
    }

    @Override
    public BigInteger submitOrder(OrderCreateReqDTO orderDTO) {
        log.info("submitOrder orderDTO :{}", orderDTO);
        OrderDO orderDO = OrderConvert.INSTANCE.convert2(orderDTO);
        orderDO.setId(orderDTO.getOrderId());

        baseMapper.updateById(orderDO);
        orderItemMapper.deleteByOrderId(orderDTO.getOrderId());
        //保存订单项 (单个sku)
        OrderItemDO orderItemDO = OrderItemDO.builder()
                .orderId(orderDO.getId())
                .categoryId(orderDTO.getCategoryId())
                .spuId(orderDTO.getSpuId())
                .spuName(orderDTO.getSpuName())
                .skuId(orderDTO.getSkuId())
                .skuName(orderDTO.getSkuName())
                .price(orderDTO.getProductPrice())
                .count(orderDTO.getAllCount())
                .deliveryType(orderDTO.getDvyType())
                .shopId(orderDTO.getShopId())
                .userId(orderDTO.getUserId())
                .spuTotalAmount(orderDTO.getTotal())
                .pic(orderDTO.getPic())
                .build();
        orderItemMapper.insert(orderItemDO);
        //删除原来的订单地址信息，换成新的地址
        orderAddrMapper.deleteByOrderId(orderDTO.getOrderId());
        //保存订单地址
        this.saveAddress(orderDTO.getOrderAddrId(), orderDTO.getUserId(), orderDO.getId(), orderItemDO.getId());

        /*
        // 锁定库存
        SkuStockLockReqDTO lockReqDTO = SkuStockLockReqDTO.builder()
                .spuId(orderDTO.getSpuId())
                .skuId(orderDTO.getSkuId())
                .orderId(orderDO.getId())
                .count(orderDTO.getAllCount())
                .build();
        CommonResult<Void> lockStockResponse = skuStockLockApi.lock(Arrays.asList(lockReqDTO));
        // 锁库存失败，抛异常回滚
        if (!lockStockResponse.isSuccess()){
            throw new ServiceException(lockStockResponse.getCode(),lockStockResponse.getMsg());
        }

        //发送延迟消息，如果三十分钟后没有支付，则取消订单,
        Boolean sendFlag = orderCancelProducer.sendOrderCancelMessage(Arrays.asList(orderDO.getId()));
        if (!sendFlag){
            // 消息发送失败，则抛异常回滚
            throw new ServiceException(MQ_SEND_FAIL);
        }
         */
        return orderDO.getId();
    }

    @Override
    public OrderDO getOrderByOrderId(BigInteger orderId) {
        return baseMapper.selectById(orderId);
    }

    @Override
    public Integer updateOrderStatus(OrderDO orderDO) {
        return baseMapper.updateById(orderDO);
    }

    @Override
    public PageResult<OrderRespVO> getMiniPage(OrderPageReqVO pageReqVO) {
        log.info("[OrderServiceImpl][getMiniPage][pageReqVO]2=={}", pageReqVO);
        PageResult<OrderDO> res = baseMapper.selectPage(pageReqVO);
        log.info("[OrderServiceImpl][getMiniPage][pageVO]3=={}", res);
        PageResult<OrderRespVO> result = OrderConvert.INSTANCE.convertMyPage(res);
        List<OrderDO> list = res.getList();
        List<OrderRespVO> resultList = new ArrayList<>();
        for (OrderDO orderDO : list) {
            OrderRespVO orderRespVO = OrderConvert.INSTANCE.convertVo(orderDO);
            orderRespVO.setOrderId(orderDO.getId());
            //查询产品信息
            List<OrderItemDO> itemDOS = orderItemService.getItemByOrderId(orderDO.getId());
            if (itemDOS != null && itemDOS.size() > 0) {
                orderRespVO.setSkuName(itemDOS.get(0).getSkuName());
                orderRespVO.setPrice(itemDOS.get(0).getPrice());
                orderRespVO.setPic(itemDOS.get(0).getPic());
            }
            orderRespVO.setOrderItems(OrderItemConvert.INSTANCE.convertVoList(itemDOS));
            //查地址
            OrderAddrDO orderAddrDO = orderAddrService.getAddrByOrderId(orderDO.getId());
            orderRespVO.setOrderAddr(OrderAddrConvert.INSTANCE.convertVo(orderAddrDO));
            resultList.add(orderRespVO);
        }
        result.setList(resultList);
        return result;
    }

    private void saveAddress(BigInteger orderAddrId, BigInteger userId, BigInteger orderId, BigInteger orderItemId) {
        if (orderAddrId == null)
            return;
        // 通过地址ID查询地址信息
        MemberAddressRespDTO address = memberAddressApi.getAddress(orderAddrId.longValue(), userId.longValue()).getCheckedData();
        OrderAddrDO addrDO = OrderAddrDO.builder()
                .orderId(orderId)
                .memberAddrId(orderAddrId)
                .orderItemId(orderItemId)
                .userId(userId)
                .consignee(address.getName())
                .provinceId(address.getProvinceId())
                .province(address.getProvince())
                .cityId(address.getCityId())
                .city(address.getCity())
                .areaId(address.getAreaId())
                .area(address.getArea())
                .addrDetail(address.getDetailAddress())
                .mobile(address.getMobile())
                .build();
        orderAddrMapper.insert(addrDO);
    }

    @Override
    public List<OrderDO> getListByDeliveryTime(OrderReqVO orderReqVO) {
        return baseMapper.selectList(orderReqVO);
    }

    @Override
    public Long getCountByStatus(int orderStatus, BigInteger shopId) {
        return baseMapper.getCountByStatus(orderStatus, shopId);
    }

    /**
     * 通过店铺ID列表获取店铺的订单数
     *
     * @param list 店铺ID列表
     * @return
     */
    @Override
    public Map<String, Object> selectCountByShopIds(List<BigInteger> list) {
        List<Map<String, Object>> mapList = baseMapper.selectCountByShopIds(list);
        Map<String, Object> collect = mapList.stream()
                .collect(Collectors.toMap(map -> map.get("shopId").toString(), map -> map.get("count"), (m1, m2) -> m2));
        return collect;
    }


    @Override
    public Integer updateOrderNo(OrderDO orderDO) {
        return baseMapper.updateOrderNo(orderDO);
    }

    @Transactional
    @Override
    public BigInteger saveOrderV2(AppOrderCreateReqVO reqVO) {
        OrderDO orderDO = OrderConvert.INSTANCE.convertV2(reqVO);
        log.info("[OrderServiceImpl][saveOrderV2] reqVO : {}", reqVO);

        baseMapper.insert(orderDO);
        List<OrderItemDO> orderItemDOS = reqVO.getOrderItems().stream().map(it -> OrderItemDO.builder()
                .orderId(orderDO.getId())
                .shopId(it.getShopId())
                .shopName(it.getShopName())
                .categoryId(it.getCategoryId())
                .spuId(it.getSpuId())
                .spuName(it.getSpuName())
                .skuId(it.getSkuId())
                .skuName(it.getSkuName())
                .price(it.getProductPrice())
                .count(it.getCount())
                .deliveryType(3)
                .userId(orderDO.getUserId())
                .spuTotalAmount(it.getTotal())
                .pic(it.getPic())
                .freightRemark(it.getFreightRemark())
                .memberPhone(reqVO.getMemberPhone())
                .payType(reqVO.getPayType())
                .orderType(orderDO.getOrderType())
                .build()).collect(Collectors.toList());
        // insertBatch不会回写id
        orderItemService.saveOrUpdateBatch(orderItemDOS);
        log.info("[OrderServiceImpl][saveOrderV2][orderItemDOS]: {}", orderItemDOS);

        // 通过地址ID查询地址信息
        if (reqVO.getOrderAddrId() != null) {
            MemberAddressRespDTO address = memberAddressApi.getAddress(reqVO.getOrderAddrId().longValue(), reqVO.getUserId().longValue()).getCheckedData();
            List<OrderAddrDO> collect = orderItemDOS.stream().map(it -> OrderAddrDO.builder()
                    .orderId(orderDO.getId())
                    .memberAddrId(BigInteger.valueOf(address.getId()))
                    .orderItemId(it.getId())
                    .userId(reqVO.getUserId())
                    .consignee(address.getName())
                    .provinceId(address.getProvinceId())
                    .province(address.getProvince())
                    .cityId(address.getCityId())
                    .city(address.getCity())
                    .areaId(address.getAreaId())
                    .area(address.getArea())
                    .addrDetail(address.getDetailAddress())
                    .mobile(address.getMobile())
                    .build()).collect(Collectors.toList());
            orderAddrMapper.insertBatch(collect);
        }
        //记录购物车的记录属于哪个订单
        if (reqVO.getShopCartId() != null) {
            shopCartItemService.updateBatchByOrderId(reqVO.getShopCartId(), orderDO.getId());
        }
        return orderDO.getId();
    }


    @Transactional
    @Override
    public BigInteger submitOrderV2(AppOrderCreateReqVO reqVO) {
        OrderDO orderDO = OrderConvert.INSTANCE.convertV2(reqVO);
        orderDO.setId(reqVO.getOrderId());
        log.info("[OrderServiceImpl][submitOrderV2]:{}", orderDO);
        log.info("[OrderServiceImpl][submitOrderV2]:{}", orderDO.getId());

        baseMapper.updateById(orderDO);
        orderItemMapper.deleteByOrderId(reqVO.getOrderId());
        //保存订单项 (多个sku)
        List<OrderItemDO> orderItemDOS = reqVO.getOrderItems().stream().map(it -> OrderItemDO.builder()
                .orderId(orderDO.getId())
                .shopId(it.getShopId())
                .shopName(it.getShopName())
                .categoryId(it.getCategoryId())
                .spuId(it.getSpuId())
                .spuName(it.getSpuName())
                .skuId(it.getSkuId())
                .skuName(it.getSkuName())
                .price(it.getProductPrice())
                .count(it.getCount())
                .deliveryType(3)
                .userId(orderDO.getUserId())
                .spuTotalAmount(it.getTotal())
                .spuActualAmount(it.getTotal())
                .pic(it.getPic())
                .memberPhone(reqVO.getMemberPhone())
                .freightRemark(it.getFreightRemark())
                .payType(reqVO.getPayType())
                .orderType(orderDO.getOrderType())
                .build()).collect(Collectors.toList());
        // insertBatch不会回写id
        orderItemService.saveOrUpdateBatch(orderItemDOS);
        log.info("[OrderServiceImpl][submitOrderV2][orderItemDOS]: {}", orderItemDOS);

        //删除原来的订单地址信息，换成新的地址
        orderAddrMapper.deleteByOrderId(reqVO.getOrderId());
        //保存订单地址
        MemberAddressRespDTO address = memberAddressApi.getAddress(reqVO.getOrderAddrId().longValue(), reqVO.getUserId().longValue()).getCheckedData();
        List<OrderAddrDO> collect = orderItemDOS.stream().map(it -> OrderAddrDO.builder()
                .orderId(orderDO.getId())
                .memberAddrId(BigInteger.valueOf(address.getId()))
                .orderItemId(it.getId())
                .userId(reqVO.getUserId())
                .consignee(address.getName())
                .provinceId(address.getProvinceId())
                .province(address.getProvince())
                .cityId(address.getCityId())
                .city(address.getCity())
                .areaId(address.getAreaId())
                .area(address.getArea())
                .addrDetail(address.getDetailAddress())
                .mobile(address.getMobile())
                .build()).collect(Collectors.toList());
        orderAddrMapper.insertBatch(collect);
        //记录购物车的记录属于哪个订单
        if (reqVO.getShopCartId() != null) {
            shopCartItemService.updateBatchByOrderId(reqVO.getShopCartId(), orderDO.getId());
        }
        //多张购物卡
        if (reqVO.getPayType() == 1 || reqVO.getPayType() == 2) {
            log.info("[OrderServiceImpl][submitOrderV2][multiLock] 添加购卡锁卡");
            List<CardMultiLockReqDTO> multiLockList = reqVO.getCardIds().stream()
                    .map(cardId -> {
                        CardMultiLockReqDTO cdto = new CardMultiLockReqDTO();
                        cdto.setCardId(cardId);
                        cdto.setOrderId(orderDO.getId());
                        return cdto;
                    }).collect(Collectors.toList());
            cardApi.multiLock(multiLockList);
            log.info("[OrderServiceImpl][submitOrderV2][multiLock]", multiLockList);
            // 添加购物卡使用记录
            cardTransactionCreate(reqVO, orderDO.getId());
        }
        // 发送延迟消息，如果三十分钟后没有支付，则取消订单
        Boolean sendFlag = orderCancelProducer.sendOrderCancelMessage(Arrays.asList(orderDO.getId()));
        log.info("[OrderServiceImpl][submitOrderV2]发送延迟消息，如果三十分钟后没有支付，则取消订单{}", sendFlag);
        if (!sendFlag) {
            // 消息发送失败，则抛异常回滚
            throw new ServiceException(MQ_SEND_FAIL);
        }
        return orderDO.getId();
    }

    private void cardTransactionCreate(AppOrderCreateReqVO reqVO, BigInteger orderId) {
        //查出所有子项的id
        List<OrderItemDO> doList= orderItemService.getItemByOrderId(orderId);
        log.info("[OrderServiceImpl][cardTransactionCreate]AppOrderCreateReqVO{}--{}", reqVO,doList);
        reqVO.setOrderItems(mapFields(doList,reqVO.getOrderItems()));
        log.info("[OrderServiceImpl][cardTransactionCreate]AppOrderCreateReqVO{}", reqVO);
        List<AppOrderItemCreateReqVO> orderItems= new ArrayList<>();
        // 添加购物卡使用记录
        distributeGiftCards(reqVO.getOrderItems() , reqVO.getCardList());

        List<CardTransactionCreateReqDTO> multiLockList = new ArrayList<>();
        reqVO.getOrderItems().forEach(order -> {
            AppOrderItemCreateReqVO appOrderItemCreateReqVO= new AppOrderItemCreateReqVO();
            appOrderItemCreateReqVO.setId(order.getId())
                            .setCardPayAmount(order.getCardUsage().stream().map(CardTransactionCreateReqDTO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add))
                            .setSpuActualAmount(order.getTotal().subtract(order.getCardUsage().stream().map(CardTransactionCreateReqDTO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add)));
            orderItems.add(appOrderItemCreateReqVO);


            log.info("订单 " + order.getId() + "（总金额" + order.getTotal() + "元）使用的总金额 " + order.getCardUsage().stream().map(CardTransactionCreateReqDTO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add) + "%n");
            order.getCardUsage().forEach(allocation -> {
                CardTransactionCreateReqDTO cdto = new CardTransactionCreateReqDTO();
                cdto.setCardId(allocation.getCardId())
                        .setShopId(order.getShopId())
                        .setRelatedOrder(orderId)
                        .setAmount(allocation.getAmount().negate())
                        .setTxnTime(LocalDateTime.now())
                        .setTxnType((byte) 2)
                        .setRelatedOrderItem(order.getId());
                multiLockList.add(cdto);
                log.info("  ▸ 使用卡号 %s 支付 %s 元 订单Id %s  %n", allocation.getCardId(), allocation.getAmount(), order.getId());
            });
        });

        log.info("[OrderServiceImpl][cardTransactionCreate]添加购物卡记录：{}",multiLockList);
        cardTransactionApi.create(multiLockList).getCheckedData();
        log.info("[OrderServiceImpl][cardTransactionCreate]添加购物卡记录：{}",multiLockList);
        //跟新订单的购物卡使用金额
        log.info("[OrderServiceImpl][cardTransactionCreate][orderItems]{}",orderItems);
        orderItemService.updateByCardPayAmount(orderItems);
        log.info("[OrderServiceImpl][cardTransactionCreate][orderItems]{}",orderItems);
        OrderDO orderDO= new OrderDO();
        orderDO.setId(orderId)
                .setCardPayAmount(orderItems.stream().map(AppOrderItemCreateReqVO::getCardPayAmount).reduce(BigDecimal.ZERO, BigDecimal::add))
                .setActualAmount(orderItems.stream().map(AppOrderItemCreateReqVO::getSpuActualAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
        log.info("[OrderServiceImpl][cardTransactionCreate][orderDO]{}",orderDO);
        baseMapper.updateById(orderDO);
    }
    public static void distributeGiftCards(List<AppOrderItemCreateReqVO> orders, List<CardRespDTO> cards) {
        log.info("[OrderServiceImpl][distributeGiftCards][orders]{}",orders);
        // 计算初始总剩余金额
        BigDecimal totalRemaining = orders.stream()
                .map(o -> o.getRemaining())
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        for (CardRespDTO card : cards) {
            if (totalRemaining.compareTo(BigDecimal.ZERO) <= 0) break;

            // 当前卡可分配上限
            BigDecimal cardLimit = card.getBalance().min(totalRemaining);

            for (AppOrderItemCreateReqVO order : orders) {
                if (cardLimit.compareTo(BigDecimal.ZERO) <= 0) break;

                // 计算当前订单分配比例（保留6位小数）
                log.info("订单："+order.getId()+"=== order.getRemaining:"+order.getRemaining()+"==totalRemaining:"+totalRemaining);
                log.info("卡："+card.getId()+"=== cardLimit:"+cardLimit);

                log.info("getTotal："+order.getTotal()+"==totalRemaining:"+totalRemaining+"=== cardLimit:"+cardLimit);
                BigDecimal ratio = order.getTotal().divide(totalRemaining, 6, RoundingMode.HALF_UP);
                log.info("卡getBalance："+card.getBalance()+"==ratio:"+ratio+"=== cardLimit:"+cardLimit);
                BigDecimal allocAmount = card.getBalance().multiply(ratio).setScale(2, RoundingMode.HALF_UP);
                log.info("卡getBalance："+card.getBalance()+"=== cardLimit:"+cardLimit);

                // 防止超额分配
                allocAmount = allocAmount.min(order.getRemaining());

                // 记录分配并更新状态
                if (allocAmount.compareTo(BigDecimal.ZERO) > 0) {
                    CardTransactionCreateReqDTO cardu=new CardTransactionCreateReqDTO();
                    cardu.setCardId(card.getId());
                    cardu.setAmount(allocAmount);
                    List <CardTransactionCreateReqDTO> s=order.getCardUsage()!=null?order.getCardUsage(): new ArrayList<>();
                    s.add(cardu);
                    order.setCardUsage(s);
                    order.setRemaining(order.getRemaining().subtract(allocAmount)) ;
                    cardLimit = cardLimit.subtract(allocAmount);
                }
            }
        }
        for (CardRespDTO card : cards) {
            // 筛选出id等于1的卡片，但不直接修改原列表
            List <CardTransactionCreateReqDTO> filteredCards = orders.stream()
                    .flatMap(item -> item.getCardUsage().stream().filter(c -> c.getCardId()==card.getId())) // 将每个AppOrderItemCreateReqVO中的List<CardRespDTO>展平
                    .collect(Collectors.toList());
            //分配的购物卡支付的总金额
            BigDecimal total = filteredCards.stream().map(CardTransactionCreateReqDTO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            //购物卡的总金额
            BigDecimal tranTotalAmt =card.getBalance();
            //取出最大的金额的数据
            Optional<CardTransactionCreateReqDTO> maxTransaction = filteredCards.stream()
                    .filter(dto -> dto.getAmount() != null) // 过滤空金额
                    .max(Comparator.comparing(CardTransactionCreateReqDTO::getAmount)); // 用BigDecimal的compareTo比较

            // TODO BigDecimal四舍五入会造成使用的购物卡金额之和大于购物卡的可用余额
            //已分配的金额>购物卡金额 ，减去多余的金额
            if (total.compareTo(tranTotalAmt) > 0){

                BigDecimal diff = total.subtract(tranTotalAmt);
                // 获取结果并修改（示例：标记为最大值）
                if (maxTransaction.isPresent()) {
                    CardTransactionCreateReqDTO maxDto = maxTransaction.get();
                    // 进行修改操作（例如：修改金额或添加标记字段）
                    maxDto.setAmount(maxDto.getAmount().subtract(diff));
                }

                //分配的购物卡支付的总金额 小于购物卡的金额，
            }else if(total.compareTo(tranTotalAmt)<0 ){
                // TODO BigDecimal 100 分3个订单分不尽的情况
                BigDecimal diff = tranTotalAmt.subtract(total);
                if(tranTotalAmt.compareTo(totalRemaining)<0 && diff.compareTo(new BigDecimal("0.01"))==0){
//                     BigDecimal diff = tranTotalAmt.subtract(total);
                    // 获取结果并修改（示例：标记为最大值）
                    if (maxTransaction.isPresent()) {
                        CardTransactionCreateReqDTO maxDto = maxTransaction.get();
                        // 进行修改操作（例如：修改金额或添加标记字段）
                        maxDto.setAmount(maxDto.getAmount().add(diff));
                    }
                }else{
                    //并且 分配的购物卡支付的订单总金额 小于 订单的应付金额
                    for(AppOrderItemCreateReqVO orderVo:orders){
                        //订单分配的购物卡金额
                        BigDecimal orderAmt= orderVo.getCardUsage().stream().map(CardTransactionCreateReqDTO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                        //订单分配的购物卡金额 小于订单的应付金额
                        if(orderAmt.compareTo(orderVo.getTotal())<0 ){
                            BigDecimal diff1 = orderVo.getTotal().subtract(orderAmt);
                            // 获取结果并修改（示例：标记为最大值）
                            if (maxTransaction.isPresent()) {
                                CardTransactionCreateReqDTO maxDto = maxTransaction.get();
                                // 进行修改操作（例如：修改金额或添加标记字段）
                                maxDto.setAmount(maxDto.getAmount().add(diff1));

                            }
                        }

                    }
                }
            }
        }
    }

    @Override
    public PageResult<AppOrderPageRespVO> getMiniPageV2(OrderPageReqVO pageReqVO) {
        log.info("[OrderServiceImpl][getMiniPageV2][pageReqVO]2=={}", pageReqVO);
        //查询用户的所有订单，分页
        PageResult<OrderDO> res = baseMapper.selectPageV2(pageReqVO);
        log.info("[OrderServiceImpl][getMiniPageV2][pageVO]3=={}", res);
        PageResult<AppOrderPageRespVO> result = OrderConvert.INSTANCE.convertMyPage02(res);

        List<OrderDO> list = res.getList();
        List<AppOrderPageRespVO> resultList = new ArrayList<>();
        //查出订单中包含的商家，拆单显示
        AppOrderPageRespVO appOrderPageRespVO = null;

        for (OrderDO orderDO : list) {
            appOrderPageRespVO = new AppOrderPageRespVO();
            appOrderPageRespVO.setOrderId(orderDO.getId());
            List<BigInteger> shopIds = orderItemService.getItemByUserId(orderDO.getUserId(), orderDO.getId());
            AppOrderListRespVO appOrderListRespVO = new AppOrderListRespVO();
            ;
            List<AppOrderListRespVO> appOrderListRespVOs = new ArrayList<>();
            for (BigInteger shopId : shopIds) {//查询商家订单
                List<OrderItemDO> itemList = orderItemService.getItemByUserIdAndShopIdAndOrderId(orderDO.getUserId(), shopId, orderDO.getId());
                appOrderListRespVO.setOrderId(orderDO.getId())
                        .setOrderStatus(orderDO.getOrderStatus())
                        .setPayTime(orderDO.getPayTime())
                        .setShopId(shopId)
                        .setShopName(shopDetailApi.getShopDetail(shopId).getCheckedData().getShopName())
                        .setOrderItems(OrderItemConvert.INSTANCE.convertVoList(itemList))
                        .setAllCount(itemList.stream().map(e -> e.getCount()).reduce(Integer::sum).get())//订单产品数量
                        .setTotal(itemList.stream().map(OrderItemDO::getSpuTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add));//订单的总金额
                appOrderListRespVOs.add(appOrderListRespVO);
            }
            //查地址
            OrderAddrDO orderAddrDO = orderAddrService.getAddrByOrderId(orderDO.getId());
            appOrderListRespVO.setOrderAddr(OrderAddrConvert.INSTANCE.convertVo(orderAddrDO));
            appOrderPageRespVO.setAppOrderListRespVOs(appOrderListRespVOs);
            resultList.add(appOrderPageRespVO);
        }
        result.setList(resultList);
        return result;
    }

    @Override
    public void updateOrderStatusV2(List<BigInteger> orderIds) {
        baseMapper.updateOrderStatusByOrderIds(orderIds);
    }

    @Override
    public List<OrderDO> selectToPaySuccess(List<BigInteger> outTradeNos) {
        return baseMapper.selectToPaySuccess(outTradeNos);
    }

    /**
     * 自动收货(分布式事务)
     *
     * @param list 订单子项list
     * @return
     */
    @GlobalTransactional(name = "csc-order-autoReceive", rollbackFor = Exception.class)
    @Override
    public int autoReceive(List<OrderItemDO> list) {
        List<OrderUpdateDeliveryReqVO> deliveryReqVOS = list.stream().map(item -> {
            OrderUpdateDeliveryReqVO vo = new OrderUpdateDeliveryReqVO();
            vo.setId(item.getId());
            vo.setOrderStatus(OrderStatusEnum.SUCCESS.value());
            vo.setFinallyTime(LocalDateTime.now());
            return vo;
        }).collect(Collectors.toList());
        //修改子项的收货状态
        orderItemService.updateBatch(deliveryReqVOS);
        List<BigInteger> orderIds = list.stream().map(OrderItemDO::getOrderId).distinct().collect(Collectors.toList());
        //修改主订单的收货状态
        this.updateOrderStatusV2(orderIds);

        // 创建分账任务
        Map<BigInteger, List<OrderItemDO>> groupedByOrderId = list.stream().collect(Collectors.groupingBy(OrderItemDO::getOrderId));
        List<OrderDO> orderDOList = this.getList(orderIds);
        Map<BigInteger, String> merchantOrderIdMap = cn.csc.framework.common.util.collection.CollectionUtils.convertMap(orderDOList, OrderDO::getId, OrderDO::getMerchantOrderId);
        log.info("[autoReceive][groupedByOrderId]:{}", groupedByOrderId);

        groupedByOrderId.forEach((key, value) -> {
            CreateDivideWithOrderItemIdReqDTO reqDTO = new CreateDivideWithOrderItemIdReqDTO();
            reqDTO.setMerchantOrderId(merchantOrderIdMap.get(key));
            reqDTO.setOrderItemIds(value.stream().map(OrderItemDO::getId).collect(Collectors.toList()));
            log.info("[autoReceive][reqDTO]:{}", reqDTO);
            payOrderApi.createDivideByOrderItemId(reqDTO);
        });
        return CollectionUtil.isEmpty(list) ? 0 : list.size();
    }

    private void decreStock(List<AppOrderItemCreateReqVO> orderItems) {
        List<SkuStockLockReqDTO> skus = orderItems.stream()
                .map(s -> SkuStockLockReqDTO.builder()
                        .skuId(s.getSkuId())
                        .spuId(s.getSpuId())
                        .count(s.getCount())
                        .build())
                .collect(Collectors.toList());
        log.info("[OrderServiceImpl][updateByToPaySuccess][skus]删除库存:{}",skus);
        skuStockLockApi.decreStock(skus);
    }
    public static List<AppOrderItemCreateReqVO> mapFields(List<OrderItemDO> dtoList,List<AppOrderItemCreateReqVO> entityList) {
        // 校验列表大小
        if (dtoList.size() != entityList.size()) {
            throw new IllegalArgumentException("列表大小必须一致");
        }

        // 按索引遍历，直接修改 entityList 中的对象
        IntStream.range(0, dtoList.size()).forEach(i -> {
            OrderItemDO dto = dtoList.get(i);
            AppOrderItemCreateReqVO entity = entityList.get(i);
            entity.setTotal(dto.getSpuTotalAmount());
            entity.setId(dto.getId());
            entity.setRemaining(dto.getSpuTotalAmount());
        });
        log.info("[OrderServiceImpl][mapFields]entityList:{}", entityList);
        return entityList;
    }

}
